// -*- c-basic-offset: 2 default-tab-width: 2 indent-tabs-mode: t -*-
// vim: autoindent tabstop=2 noexpandtab shiftwidth=2 softtabstop=2
//===------------ Lambda.h
//
//             This file is part of the reactor project
//                Author: R-Core Team
//
//===---------------------------------------------------------------------===//

#ifndef LAMBDA_H_
#define LAMBDA_H_

#include "Any.h"
#include "Atom.h"
#include "llvm/Function.h"

#include "CVector.h"
//#include "RJITCompiler.h"

namespace R {
	class RModule;
	class Symbol;
	class Bindings;
	class Environment;
	class FunInfo;
	struct pattern_t;

	typedef Any* (*rFunPtr)();

	struct ReadSetEntry {
		Symbol *symbol;
		int		hops;
		int		position;

		ReadSetEntry(): symbol(NULL), hops(0), position(0){};
		ReadSetEntry(Symbol *s, int h, int pos): symbol(s), hops(h), position(pos){};
	};

	class ReadSet: public CVector<ReadSetEntry> {
		public:
		static void remove(Symbol* sym, CVector<Symbol*> *set) {
			R_PARAM(sym);
			R_VAR(Symbol*, other);

			int pos = set->has(sym);
			if(pos >= 0) {
				other = set->pop();
				if(pos != set->size())
					set->set(other, pos);
			}
		}

		ReadSetEntry* lookup(Symbol *sym) {
			R_PARAM(sym);
			for(int i = 0; i < size(); i++) {
				ReadSetEntry *rse = &get(i);
				if(rse->symbol == sym)
					return rse;
			}
			return NULL;
		}

		void add(Symbol *sym, FunInfo *current);
	};


	class FunInfo : public vmkit::PermanentObject {
	public:
		uint32_t  id;

		RModule*  module;
		uint32_t  start;
		uint32_t  end;

		llvm::Function* jitFun;
		rFunPtr code;
		bool isCall;

		Bindings* bindings;
		struct pattern_t* dstruct;// For destructurate argument matching

		bool      hasDot;
		uint32_t  hasClosure;

		CVector<Symbol*>	writeSet;
		ReadSet						readSet;

		FunInfo		*parent;

		FunInfo(){
			id=0;
			module=NULL;
			start=0;
			end=0;
			jitFun=NULL;
			isCall=false;
			hasDot=false;
			hasClosure=0;
			code = NULL;
			bindings = NULL;
			parent = NULL;
		}

		r_bool       isClosure(){ return bindings != NULL ; }

		void         print();

		void         makeFormals(cpool_entry *params, cpool_entry *cpool);

		Any*         getVar(Symbol *sym, bool *has);

		//void matchParams(Environment *env);

		virtual void tracer(uint64_t closure);
	};

	class Lambda : public Atom {
	  BASE_ABSTRACT_RCLASS(Lambda)
	  public:
		FunInfo      *fun;
		virtual void tracer(word_t closure);
	};
}

#endif /* LAMBDA_H_ */
